package com.huawei.deveco.common.security.util;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.CopyOption;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;

public class FilePermissionUtil {
    public static void copyFileWithPermission(Path src, Path des) throws IOException {
        Files.copy(src, des, new CopyOption[]{StandardCopyOption.REPLACE_EXISTING});
        if (OsTypeUtil.isWindows())
            return;
        FileStore fileStore = Files.getFileStore(src);
        boolean canSupportPosix = fileStore.supportsFileAttributeView((Class) PosixFileAttributeView.class);
        if (canSupportPosix) {
            Set<PosixFilePermission> posixFilePermissions = Files.getPosixFilePermissions(src, new java.nio.file.LinkOption[0]);
            Files.setPosixFilePermissions(des, EnumSet.copyOf(posixFilePermissions));
        }
    }

    public static void createMaterialDirsWithPermission(Path materialDir) throws IOException {
        if (OsTypeUtil.isWindows()) {
            Files.createDirectories(materialDir, (FileAttribute<?>[]) new FileAttribute[0]);
        } else {
            Files.createDirectories(materialDir, (FileAttribute<?>[]) new FileAttribute[]{getPosixFileAttribute("rwx------")});
        }
    }

    public static void createMaterialFileOrWriteBytesWithPermission(Path filePath, byte[] bytes) throws IOException {
        ensureParentDir(filePath);
        Set<OpenOption> options = new HashSet<>();
        options.add(StandardOpenOption.CREATE);
        options.add(StandardOpenOption.WRITE);
        options.add(StandardOpenOption.TRUNCATE_EXISTING);
        if (OsTypeUtil.isWindows()) {
            writeBytes(filePath, bytes, options, (FileAttribute<?>[]) new FileAttribute[0]);
        } else {
            writeBytes(filePath, bytes, options, (FileAttribute<?>[]) new FileAttribute[]{getPosixFileAttribute("rw-------")});
        }
    }

    private static void ensureParentDir(Path filePath) throws IOException {
        Path parent = filePath.getParent();
        if (parent != null && Files.notExists(parent, new java.nio.file.LinkOption[0]))
            createMaterialDirsWithPermission(parent);
    }

    private static void writeBytes(Path filePath, byte[] bytes, Set<OpenOption> options, FileAttribute<?>... attr) throws IOException {
        SeekableByteChannel seekableByteChannel = Files.newByteChannel(filePath, options, attr);
        try {
            if (bytes == null || bytes.length == 0) {
                if (seekableByteChannel != null)
                    seekableByteChannel.close();
                return;
            }
            seekableByteChannel.write(ByteBuffer.wrap(bytes));
            if (seekableByteChannel != null)
                seekableByteChannel.close();
        } catch (Throwable throwable) {
            if (seekableByteChannel != null)
                try {
                    seekableByteChannel.close();
                } catch (Throwable throwable1) {
                    throwable.addSuppressed(throwable1);
                }
            throw throwable;
        }
    }

    private static FileAttribute<?> getPosixFileAttribute(String permString) {
        Set<PosixFilePermission> permissions = PosixFilePermissions.fromString(permString);
        return PosixFilePermissions.asFileAttribute(permissions);
    }
}
